﻿using Microsoft.Extensions.DependencyInjection;
using Modules.System.User;
using PetaPoco;
using Pipelines.Sockets.Unofficial.Arenas;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Entity;
using PmSoft.Repositories;
using PmSoft.Utilities;

namespace Modules.Project.Repositories
{
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectGuaranteePaymentRepository : Repository<ProjectGuaranteePayment, DefaultDbContext>
    {
        private readonly IApplicationContext applicationContext;

        public ProjectGuaranteePaymentRepository(DefaultDbContext dbContext, IApplicationContext applicationContext) : base(dbContext, applicationContext)
        {
            this.applicationContext = applicationContext;
        }

        /// <summary>
        /// author:hzj date:2023/12/22 describe:分页获取保证金缴纳记录
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<ProjectGuaranteePayment> GetProjectGuaranteePayments(ProjectGuaranteePaymentQuery query, int pageIndex, int pageSize)
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
                .From("project_guarantee_payment");

            #region 主管单位数据权限

            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                if (deptUser.IsRSAdministrator())
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0  ");
                }
                else
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0 ", deptUser.IndustryType);
                }
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }

            #endregion 主管单位数据权限

            if (!string.IsNullOrEmpty(query.Keywords))
                sql.Where("(payment_name Like @0 or payment_code Like @0 )", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.ProjectId.HasValue)
                sql.Where("project_guarantee_payment.project_id=@0", query.ProjectId);
            if (query.GuaranteeAccountId.HasValue)
                sql.Where("project_guarantee_payment.guarantee_account_id=@0", query.GuaranteeAccountId);
            if (query.Status.HasValue)
            {
                sql.Where("project_guarantee_payment.status=@0", query.Status);
            }
            if (query.HasReturn.HasValue)
            {
                sql.Where("project_guarantee_payment.has_return=@0", query.HasReturn.Value ? 1 : 0);
            }
            if (query.AccountType.HasValue)
            {
                sql.InnerJoin("project_guarantee_account").On("project_guarantee_payment.guarantee_account_id=project_guarantee_account.id").Where("project_guarantee_account.type=@0", query.AccountType.Value);
            }
            sql.OrderBy("project_guarantee_payment.create_time DESC");
            return GetPagingEntities(pageSize, pageIndex, sql);
        }

        public ProjectGuaranteePayment? GetProjectGuaranteePaymentByProjectId(int projectId)
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
               .From("project_guarantee_payment")
               .Where("project_id=@0", projectId)
               .Where("status=1")
               .Where("has_return=0 ")
               .OrderBy("create_time DESC");
            return Get(DbContext.FirstOrDefault<int>(sql));
        }

        /// <summary>
        /// 根据账户来获取缴纳信息
        /// </summary>
        /// <param name="guaranteeAccountId"></param>
        /// <returns></returns>
        public IEnumerable<ProjectGuaranteePayment> GetProjectGuaranteePayments(int guaranteeAccountId)
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
                .From("project_guarantee_payment");

            #region 主管单位数据权限

            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                if (deptUser.IsRSAdministrator())
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0 ");
                }
                else
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0 ", deptUser.IndustryType);
                }
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }

            #endregion 主管单位数据权限

            sql.Where("guarantee_account_id=@0", guaranteeAccountId);
            sql.OrderBy("project_guarantee_payment.create_time DESC");
            return PopulateEntitiesByEntityIds(DbContext.FetchFirstColumn<int>(sql));
        }

        /// <summary>
        /// 根据查询条件获取总行数
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public int GetProjectGuaranteePaymentCount(ProjectGuaranteePaymentQuery query)
        {
            Sql sql = Sql.Builder;
            sql.Select("count(id)")
                .From("project_guarantee_payment");

            #region 主管单位数据权限

            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                if (deptUser.IsRSAdministrator())
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0 ");
                }
                else
                {
                    sql.InnerJoin("project as prj").On($"project_guarantee_payment.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0 ", deptUser.IndustryType);
                }
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }

            #endregion 主管单位数据权限

            if (!string.IsNullOrEmpty(query.Keywords))
                sql.Where("(payment_name Like @0 or payment_code Like @0 )", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.ProjectId.HasValue)
                sql.Where("project_guarantee_payment.project_id=@0", query.ProjectId);
            if (query.GuaranteeAccountId.HasValue)
                sql.Where("project_guarantee_payment.guarantee_account_id=@0", query.GuaranteeAccountId);
            if (query.Status.HasValue)
            {
                sql.Where("project_guarantee_payment.status=@0", query.Status);
            }
            if (query.HasReturn.HasValue)
            {
                sql.Where("project_guarantee_payment.has_return=@0", query.HasReturn.Value ? 1 : 0);
            }
            return DbContext.Fetch<int>(sql).FirstOrDefault();
        }

        /// <summary>
        /// 判断项目下是否存在有效的保证金
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public bool ExistProjectGuaranteePayment(int projectId)
        {
            return DbContext.Exists<ProjectGuaranteePayment>("project_id=@0 AND (status=@1 or status=@2)", projectId, 保证金状态.有效, 保证金状态.待核实);
        }

        /// <summary>
        /// 标记所有保证金账户失效
        /// </summary>
        public IEnumerable<ProjectGuaranteePayment> MarkPaymentExpire()
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
                .From("project_guarantee_payment")
                .Where("status=@0 and end_date is not null and end_date <NOW()", 保证金状态.有效);
            return PopulateEntitiesByEntityIds(DbContext.Fetch<int>(sql));
        }

        public IEnumerable<ProjectGuaranteePayment> GetProjectGuaranteePaymentsByStatus(保证金退还状态 status)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("Status", status);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"ProjectCorpWageAuthByProjectId:{status}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("project_guarantee_payment")
                .Where("status=@0", status);
                return sql;
            });
        }

        internal IEnumerable<ProjectGuaranteePayment> GetProjectGuaranteePaymentsByProjectIds(IEnumerable<int> projectIds)
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
            .From("project_guarantee_payment")
            .Where("project_id in (@0)", projectIds)
            .Where("status=1")
            .Where("has_return=0 ")
            .OrderBy("create_time DESC");

            return PopulateEntitiesByEntityIds(DbContext.Fetch<int>(sql));
        }
    }
}